//
// Created by gogoqiu on 2021/8/31.
//

#include "GitListFrame.h"
#include "AddRepDialog.h"
#include "utils.h"


#define SQLITE_PATH "reps.db"
/*
 * dialogRootBoxSizer
 *  scrollWindow
 *      wxBoxSizer
 *          panel
 *
 */
GitListFrame::GitListFrame()
        : wxFrame(nullptr, wxID_ANY, "Hello World",
                  wxDefaultPosition, wxSize(400,641),
                  wxDEFAULT_FRAME_STYLE ^ wxMAXIMIZE_BOX ^ wxRESIZE_BORDER )
{
    int ret = sqlite3_open( SQLITE_PATH, &m_pDb );
    if( ret != SQLITE_OK ){
        exit(-1);
    }
    InitDB();

    Center();
    auto *menuFile = new wxMenu;
    menuFile->Append(ID_ADD_REPO, "&Add...\tCtrl-H",
                     "Help string shown in status bar for this menu item");
    menuFile->AppendSeparator();
    menuFile->Append(wxID_EXIT);
    auto *menuHelp = new wxMenu;
    menuHelp->Append(wxID_ABOUT);
    auto *menuBar = new wxMenuBar;
    menuBar->Append(menuFile, "&File");
    menuBar->Append(menuHelp, "&Help");
    SetMenuBar( menuBar );
    CreateStatusBar();
    SetStatusText("Welcome to wxWidgets!");

    /*
     * wxBoxSizer *panelRootBoxSizer;
    wxBoxSizer *dialogRootBoxSizer;
    wxScrolledWindow* m_listbox;
     */
    dialogRootBoxSizer = new wxBoxSizer(wxVERTICAL);
    m_listbox = new wxScrolledWindow(this, wxID_ANY,
                                     wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL );
    m_listbox->SetScrollRate(5, 5 );
    dialogRootBoxSizer->Add(m_listbox, 1, wxEXPAND, 0 );
    m_listbox->SetBackgroundColour(wxColour(0, 128, 192 ) );
    //return;
    //wxBoxSizer *BoxSizer = new wxBoxSizer(wxHORIZONTAL);
    panelRootBoxSizer = new wxBoxSizer(wxVERTICAL);
    //auto *bt_add = new wxButton( m_listbox, ID_ADD_REPO , _T("添加仓库" ), wxDefaultPosition, wxSize(50, 20));
    //panelRootBoxSizer->Add( bt_add, 1,
    //                        wxTILE|wxALIGN_CENTER_HORIZONTAL, 2 );

    //bt_add->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler( GitListDialog::AddRep  ),
    //                nullptr, this );
    m_listbox->SetSizer(panelRootBoxSizer );
    m_listbox->Layout();
    //m_listbox->AddChild( bt_add );
    this->SetSizer(dialogRootBoxSizer);
    Layout();
    Bind(wxEVT_MENU, &GitListFrame::AddRep, this, ID_ADD_REPO );
    LoadAll();
}

int GitListFrame::InitDB(){
    char *errmsg;
    /* 创建表 */
    const char *sql = "CREATE TABLE reps("
                      "id INTEGER PRIMARY KEY,"
                      "`type` INTEGER,"
                      "path TINYTEXT );" ;

    sqlite3_exec( m_pDb,sql,nullptr, nullptr, &errmsg );
#ifdef _DEBUG_
    printf("%s\n",errmsg);
    //sqlite3_free(errmsg);
#endif
    sqlite3_free(errmsg);
    return 0;
}

/**
 * 拖拽排序
 * @return
 */
int GitListFrame::LoadAll(){
    wxString sql;
    sql.sprintf("select * from reps;");
    const char * _sql = sql.mb_str(wxConvUTF8);

    char *errmsg;
    int result;
    int nRow, nColumn;
    int i , j;
    int index;
    char **dbResult; //是 char ** 类型，两个*号
    result = sqlite3_get_table( m_pDb, _sql, &dbResult, &nRow, &nColumn, &errmsg );
    wxString path;
    char* type;
    bool _valueIsNull;
    //
    Rep *rep;
    if( SQLITE_OK == result )
    {
        //查询成功
        index = nColumn; //前面说过 dbResult 前面第一行数据是字段名称，从 nColumn 索引开始才是真正的数据
        //printf( "查到%d条记录/n", nRow );

        for(  i = 0; i < nRow ; i++ )
        {
            for( j = 0 ; j < nColumn; j++ )
            {
                switch (j) {
                    case 0:
                        break;
                    case 1:
                        type = dbResult [index];
                        break;
                    case 2:
                        path = dbResult [index];
                        break;
                }
                //printf( "字段名:%s, 字段值:%s\n",  dbResult[j], dbResult [index] );
                ++index; // dbResult 的字段值是连续的，从第0索引到第 nColumn - 1索引都是字段名称，从第 nColumn 索引开始，后面都是字段值，它把一个二维的表（传统的行列表示法）用一个扁平的形式来表示
            }
            if( *type==0 )
                rep = new Rep( GIT, path );
            else
                rep = new Rep( SVN, path );
            this->reps.push_back( rep );
            //build the rep view
            appendView( rep );
        }
    }
    //到这里，不论数据库查询是否成功，都释放 char** 查询结果，使用 sqlite 提供的功能来释放
    sqlite3_free_table( dbResult );
    //关闭数据库
    //sqlite3_close( m_pDb );
    return 0;
}

int GitListFrame::RunSql( const wxString& sql ){
    char *errmsg;
    const char *_sql;
    _sql = sql.mb_str(wxConvUTF8);
    int ret = sqlite3_exec(m_pDb, _sql,nullptr, nullptr, &errmsg);
    if( ret!=SQLITE_OK ) {
#ifdef _DEBUG_
        printf("%s\n%s\n", _sql, errmsg);
#endif
        sqlite3_free(errmsg);
        return -1;
    }
    return 0;
}
//restore

/*
 * 如何刷新界面
 * 存数据
 * 如何
 */
void GitListFrame::AddRep( wxCommandEvent& event ){
    //reps.
    Rep *rep = new Rep;
    AddRepDialog dialog( this, rep );
    if ( dialog.ShowModal() == wxID_OK ) {
        for(auto & rep : reps){
            if( rep->path.IsSameAs(rep->path))
                return;
        }
        this->reps.push_back( rep );
        //update to sqlite
        wxString sql;
        sql.sprintf("insert into reps ( type, path ) values( %d, '%s' );", rep->type, rep->path );
        RunSql( sql );
        //printf( "size: %d\n", reps.size() );
        //
        appendView( rep );
    }
}

/*
 *
 */
void GitListFrame::appendView( Rep* rep ){
    auto* panel = new GitPanel(m_listbox, rep->path, rep->type );
    //wxStaticText *s_path = new wxStaticText( this, wxID_ANY, "path",
    //                                         wxDefaultPosition, wxDefaultSize, 0 );
    panelRootBoxSizer->Add(panel, 1,
                           wxTILE|wxALIGN_CENTER_HORIZONTAL, 5  );
    m_listbox->SetSizer(panelRootBoxSizer);

    auto *object = new MyObj( panel );
    panel->get_s_path()->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( GitListFrame::RemoveRep  ),
                                  object, this );
    Layout();
}

//double click
void GitListFrame::RemoveRep( wxMouseEvent& event ){
    auto *myObj = reinterpret_cast<MyObj *>(event.GetEventUserData());
    auto *panel = reinterpret_cast<GitPanel*>(myObj->data);
    wxString path(panel->getPath());
    printf("%s\n", path.c_str().AsChar() );
}

GitListFrame::~GitListFrame(){
    if( m_pDb ) {
        sqlite3_close(m_pDb);
    }
    for(auto & rep : reps){
        delete rep;
    }
}